package be.destin.rdf.changes;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;

import be.destin.skos.core.SchemeFactory;
import be.destin.skos.core.SchemeInterface;
import be.destin.skos.core.SkosManager;

public class ChangeManager {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final String changeConfiguration = "changeAssertions";

	/** log4j category */
	private static Logger log = Logger.getLogger(SkosStatement.class);

	private final float hashTableLoadFactor = 0.75f;

	protected int cacheSize = 0;

	private SkosManager skosManager;

	private LinkedHashMap<Integer, SkosStatement> entries = null;

	private Properties properties = null;
	
	public ChangeManager (SkosManager skosManager) {
		this.skosManager = skosManager;
		loadConfigFile();
		
	}
	
	private void loadConfigFile() {
		String configFile = skosManager.getConfigDirectory()+changeConfiguration+SchemeFactory.configExtension;
		log.debug("Assertion source configuration: "+configFile);
		this.properties = SchemeFactory.readPropertyFile(configFile);
	}
	
	public SkosStatement getStatement(long ID) {
		SkosStatement result = entries.get(ID);
		if (result != null) {
			return result;
		} else return readStatement(ID);
	}
	
	SkosStatement readStatement (long ID) {
		return null;
	}
	/**
	 * @param newCacheSize
	 */
	public synchronized void setCacheSize(int newCacheSize) {
		if (newCacheSize > cacheSize) { // Cache can only grow!
			cacheSize = newCacheSize;
			int hashTableCapacity = (int) Math.ceil(cacheSize
					/ hashTableLoadFactor) + 1;
			LinkedHashMap<Integer, SkosStatement> newEntries = new LinkedHashMap<Integer, SkosStatement>(hashTableCapacity,
					hashTableLoadFactor, true) {
				// An anonymous inner class to define a procedure which decides when cache is full
				private static final long serialVersionUID = 1;

				/*
				 * Manages the eldest entry when it has to be removed (cache full)
				 */
				protected boolean removeEldestEntry(Map.Entry<Integer, SkosStatement> eldest) {
					if (size() > cacheSize) {
						SkosStatement eldestStmt = eldest.getValue();
						if (eldestStmt != null)
							removeMappings(eldestStmt);
						return true;
					}
					else return false;
				}
			};
			if (entries != null) {
				newEntries.putAll(entries);
			}
			entries = newEntries;
		};
	}

	/*
	 * Ensures a new cache is set up
	 */
	public synchronized void setRenewedCacheSize(int cacheSize) {
		entries = null;
		this.cacheSize = -1;
		setCacheSize(cacheSize);
	}

	/*
	 * Remove the indexes pointing to a concept when this one is released from the cache (or from the scheme)
	 */
	protected void removeMappings(SkosStatement aStatement) {
		// 	No mappings for now...
	}

	public SkosManager getSkosManager() {
		return skosManager;
	}

	public void setSkosManager(SkosManager skosManager) {
		this.skosManager = skosManager;
	}

	public long mergeRdfStatements(SchemeInterface aScheme) {
		// read all RDF statements for that scheme
		// Browse the result
		// build the statements
		// if they do not exist, add them if not deprecated...
		return 0;
	}
}
